﻿using System;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace Uranus.Common
{
    public class DESCommon
    {
        private static string _key;
        private static string _iv;
        private static bool _secretEnable = false;

        /// <summary>
        /// 加密串
        /// </summary>
        public static string Key
        {
            get
            {
                if (_key == null)
                {
                    throw new Exception("iv尚未定义");
                }
                return _key;
            }
            set
            {
                if (_key == null)
                {
                    _key = value;
                }
            }
        }
        public static string Iv
        {
            get
            {
                if (_iv == null)
                {
                    throw new Exception("iv尚未定义");
                }
                return _iv;
            }
            set
            {
                if (_iv == null)
                {
                    _iv = value;
                }
            }
        }
        /// <summary>
        /// 是否启用加密 默认true
        /// </summary>
        public static bool SecretEnable
        {
            get
            {
                return _secretEnable;
            }
            set
            {
                _secretEnable = value;
            }
        }
        #region DES加解密

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="toEncrypt">加密串</param>
        /// <returns></returns>
        public static string Encrypt(string toEncrypt)
        {
            return Encrypt(toEncrypt, _key, _iv);
        }
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="toEncrypt"> 加密串 </param>
        /// <param name="key"> 16位key</param>
        /// <param name="iv"> 16位key</param>
        /// <returns></returns>
        private static string Encrypt(string toEncrypt, string key, string iv)
        {
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
            byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
            byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.IV = ivArray;
            rDel.Mode = CipherMode.CBC;
            rDel.Padding = PaddingMode.Zeros;

            ICryptoTransform cTransform = rDel.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="toDecrypt">解密串</param>
        /// <returns></returns>
        public static string Decrypt(string toDecrypt)
        {
            return Decrypt(toDecrypt, _key, _iv);
        }
        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="toDecrypt"> 解密串 </param>
        /// <param name="key"> 16位key</param>
        /// <param name="iv"> 16位key</param>
        /// <returns></returns>
        private static string Decrypt(string toDecrypt, string key, string iv)
        {
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
            byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
            byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);

            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.IV = ivArray;
            rDel.Mode = CipherMode.CBC;
            rDel.Padding = PaddingMode.Zeros;

            ICryptoTransform cTransform = rDel.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            return UTF8Encoding.UTF8.GetString(resultArray);
        }

        #endregion

        #region 可变解密
        public static bool LoadData(ref string str)
        {
            if (_secretEnable)
            {
                if (!string.IsNullOrEmpty(str))
                {
                    try
                    {
                        str = Decrypt(str).TrimEnd('\0');
                        return true;
                    }
                    catch (Exception ex)
                    {
                        if (ex.Message.Contains("长度无效"))
                        {
                            return false;
                        }
                        else
                        {
                            throw ex;
                        }
                    }
                }
                else return false;
            }
            return true;
        }
        public static bool LoadData(ref string str, ref string str1)
        {
            return (LoadData(ref str) && LoadData(ref str1));
        }
        public static bool LoadData(ref string str, ref string str1, ref string str2)
        {
            return (LoadData(ref str, ref str1) && LoadData(ref str2));
        }
        public static bool LoadData(ref string str, ref string str1, ref string str2, ref string str3)
        {
            return (LoadData(ref str, ref str1, ref str2) && LoadData(ref str3));
        }
        public static bool LoadData(ref string str, ref string str1, ref string str2, ref string str3, ref string str4)
        {
            return (LoadData(ref str, ref str1, ref str2, ref str3) && LoadData(ref str4));
        }
        public static bool LoadData(ref string str, ref string str1, ref string str2, ref string str3, ref string str4, ref string str5)
        {
            return (LoadData(ref str, ref str1, ref str2, ref str3, ref str4) && LoadData(ref str5));
        }
        public static bool LoadData(ref string str, ref string str1, ref string str2, ref string str3, ref string str4, ref string str5, ref string str6)
        {
            return (LoadData(ref str, ref str1, ref str2, ref str3, ref str4, ref str5) && LoadData(ref str6));
        }
        public static bool LoadData(ref string str, ref string str1, ref string str2, ref string str3, ref string str4, ref string str5, ref string str6, ref string str7)
        {
            return (LoadData(ref str, ref str1, ref str2, ref str3, ref str4, ref str5, ref str6) && LoadData(ref str7));
        }
        public static bool LoadData(ref string str, ref string str1, ref string str2, ref string str3, ref string str4, ref string str5, ref string str6, ref string str7, ref string str8)
        {
            return (LoadData(ref str, ref str1, ref str2, ref str3, ref str4, ref str5, ref str6, ref str7) && LoadData(ref str8));
        }
        public static bool LoadData(ref string str, ref string str1, ref string str2, ref string str3, ref string str4, ref string str5, ref string str6, ref string str7, ref string str8, ref string str9)
        {
            return (LoadData(ref str, ref str1, ref str2, ref str3, ref str4, ref str5, ref str6, ref str7, ref str8) && LoadData(ref str9));
        }
        public static bool LoadData(ref string str, ref string str1, ref string str2, ref string str3, ref string str4, ref string str5, ref string str6, ref string str7, ref string str8, ref string str9, ref string str10)
        {
            return (LoadData(ref str, ref str1, ref str2, ref str3, ref str4, ref str5, ref str6, ref str7, ref str8, ref str9) && LoadData(ref str10));
        }
        #endregion

        /// <summary>
        /// 根据KEY加密
        /// </summary>
        /// <param name="Text"></param>
        /// <param name="Key"></param>
        /// <returns></returns>
        public static string EncryptByKey(string Text, string Key)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] inputByteArray;
            inputByteArray = Encoding.Default.GetBytes(Text);
            des.Key = ASCIIEncoding.ASCII.GetBytes(Key);
            des.IV = ASCIIEncoding.ASCII.GetBytes(Key);
            des.Mode = CipherMode.CBC;
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                cs.FlushFinalBlock();
                cs.Close();
            }
            string str = Convert.ToBase64String(ms.ToArray());
            ms.Close();
            return str;

        }

        /// <summary>
        /// 根据KEY解密
        /// </summary>
        /// <param name="Text"></param>
        /// <param name="Key"></param>
        /// <returns></returns>
        public static string DecryptByKey(string Text, string Key)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] inputByteArray = Convert.FromBase64String(Text);//Encoding.UTF8.GetBytes(source);

            des.Key = ASCIIEncoding.ASCII.GetBytes(Key);
            des.IV = ASCIIEncoding.ASCII.GetBytes(Key);
            des.Mode = CipherMode.CBC;
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
            {
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                cs.FlushFinalBlock();
                cs.Close();
            }
            string str = Encoding.UTF8.GetString(ms.ToArray());
            ms.Close();
            return str;
        }

        /// <summary>
        /// 中文转码
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string UnCode(string str)
        {
            string outStr = "";
            //Regex reg = new Regex(@"(?i)//u([0-9a-f]{4})");
            //outStr = reg.Replace(str, delegate(Match m1)
            //{
            //    return ((char)Convert.ToInt32(m1.Groups[1].Value, 16)).ToString();
            //});
            //return outStr;
            if (!string.IsNullOrEmpty(str))
            {
                for (int i = 0; i < str.Length; i++) 
                {
                    outStr += "//u" + ((int)str[i]).ToString("x");
                }
            }

            return outStr;
        }
        /// <summary>
        /// 中文转unicode
        /// </summary>
        /// <returns></returns>
        public static string unicode(string str)
        {
            string outStr = "";
            string a = "";
            if (!string.IsNullOrEmpty(str))
            {
                for (int i = 0; i < str.Length; i++)
                {
                    if (Regex.IsMatch(str[i].ToString(), @"[\u4e00-\u9fa5]")) { outStr += "\\u" + ((int)str[i]).ToString("x"); }
                    else { outStr += str[i]; }
                }
            }
            return outStr;
        } 
    }
}